//***************************************************************************************************
//  Ensemble de primitives permmettant de disposer d'une horloge bas�e sur le timer 0 en interruption
// V1.0
//  attention cette version n'est pas  utilisable avec un UART logiciel car la dur�e actuelle du serveur
// est de 734 us � 4MHz !!
//  Etat: OK test� en simulation
// TODO : passer en assembleur sur le serveur IT pour reduire temps d'ex�xution et pourvoir faire
//        coexister l'horloge avce des UART logiciels
//****************************************************************************************************

#include "gestionTempsMC.h"

#define MAX_WATCHDOGS 3

//*************variables globales *******************
static unsigned int gl_valInitTimer0;
static unsigned long int gl_dateEnTic;
unsigned long int gl_dateTimeOut[MAX_WATCHDOGS];
unsigned long int litDate(void);
//****************************************************

char initClock (void)
{  
    gl_dateEnTic = 0;

    gl_dateTimeOut[0] = 0;
    gl_dateTimeOut[1] = 0;
    gl_dateTimeOut[2] = 0;

    gl_valInitTimer0 = 40536;

    INTCON2bits.TMR0IP = 1; // timer 0 en priorite haute

    RCONbits.IPEN = 1; // valide hierachie des IT

    OpenTimer0( TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & PRESCALE_TIMER & T0_EDGE_FALL );

    WriteTimer0( gl_valInitTimer0 );

    INTCONbits.GIEH = 1; // autorise les interruptions priorite haute

    T0CONbits.TMR0ON = 1;
}

//****************************************************************
// retourne la date courante en tic d'horloge
//*****************************************************************
unsigned long int litDate(void)
{
  unsigned long int date;

  INTCONbits.TMR0IE = 0; // bloque IT timer

  date = gl_dateEnTic;

  INTCONbits.TMR0IE = 1; // autorise IT timer

  return date;
}

//****************************************************************
// armement minuterie
//*****************************************************************
void setWatchDog(unsigned int delaiEnSec, char numWD)
{
    unsigned long int dateCour;

    dateCour = litDate();

    gl_dateTimeOut[numWD] = dateCour + delaiEnSec * 10;
}

unsigned long int  getTimeLeft(char numWD)
{
    unsigned long int dateCour;

    dateCour = litDate();

    return (gl_dateTimeOut[numWD] - dateCour)/10;
}
//****************************************************************
// teste si minuterie arrive � �ch�ance
// Retourne VRAI si  le d�lai d'armement est pass�
// non bloquant
//*****************************************************************
char checkWatchDog(char numWD)
{
    unsigned long int dateCur = litDate();
	if (dateCur >= gl_dateTimeOut[numWD])
            return VRAI;
  	else
            return FAUX;
}

//****************************************************************
// bloque horloge en masquant IT timer 0
//*****************************************************************
void figeHorloge(void)
{
    T0CONbits.TMR0ON = 0;
}
//****************************************************************
// reprend horloge en demasquant IT timer 0
//*****************************************************************
void reprendHorloge(void)
{
    T0CONbits.TMR0ON = 1;
}

//****************************************************************
// remise� 0 de la date
//*****************************************************************
void resetDate()
{	
	INTCONbits.TMR0IE=0; // bloque IT timer
	
	gl_dateEnTic=0;
	
	INTCONbits.TMR0IE=1; // autorise IT timer
}

//************************  serveur d'interruption timer 0*******************************************************//
// High priority interrupt vector

#pragma code InterruptVectorHigh = 0x08
void
InterruptVectorHigh (void)
{
  _asm
    goto serveurTimer0 //jump to interrupt routine
  _endasm
}

//----------------------------------------------------------------------------
// High priority interrupt routine

#pragma code
#pragma interrupt serveurTimer0

void serveurTimer0 ()
{
  if (INTCONbits.TMR0IF)
    {                                   // check for TMR0 overflow
      INTCONbits.TMR0IF = 0;            // clear interrupt flag
      WriteTimer0(gl_valInitTimer0); 	// recharge la valeur dans le compteur
      gl_dateEnTic ++;
    }
}

void delaySec(int sec)
{
    setWatchDog(sec, WD_TEMPO);
    while(checkWatchDog(WD_TEMPO) == FAUX);
}